﻿using Windows.Foundation;
using CommunityToolkit.WinUI;
using DimensionsHelper.Client.WinUi.Contracts;

namespace DimensionsHelper.Client.WinUi.Controls;

public partial class DataTableViewRow : Panel
{
    public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register(
        nameof(ItemsSource),
        typeof(IEnumerable),
        typeof(DataTableViewRow),
        new PropertyMetadata(null, OnItemsSourcePropertyChanged));

    private Panel? _headerPanel;
    private WeakReference<DataTableView>? _headerTable;

    private bool _isCellsInitialized;


    public DataTableView? HeaderTable
    {
        get => _headerTable?.TryGetTarget(out DataTableView? tableView) is true ? tableView : null;
        set => _headerTable = value is null ? null : new WeakReference<DataTableView>(value);
    }


    public IEnumerable? ItemsSource
    {
        get => GetValue(ItemsSourceProperty) as IEnumerable;
        set => SetValue(ItemsSourceProperty, value);
    }


    private static void OnItemsSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        DataTableViewRow row = (DataTableViewRow)d;
        row.Children.Clear();
        row._isCellsInitialized = false;
        row.GenerateCellsByItemsSource();
        row.InvalidateArrange();
    }


    private static TextBlock GenerateCell(object? content)
    {
        TextBlock? cell = new()
        {
            Margin = new Thickness(2, 0, 2, 0),
            Text = content?.ToString() ?? string.Empty,
            TextWrapping = TextWrapping.NoWrap
        };

        ToolTipService.SetToolTip(cell, cell.Text);
        return cell;
    }


    private void GenerateCellsByItemsSource()
    {
        IEnumerable? source = ItemsSource;

        if (_isCellsInitialized || source is null)
        {
            return;
        }

        IStringMap? stringMap = source as IStringMap;

        // 只有设置了列定义，关键字枚举才有效
        if (HeaderTable is not null)
        {
            foreach (DataTableViewColumn? column in HeaderTable.Children.OfType<DataTableViewColumn>())
            {
                Children.Add(GenerateCell(stringMap?.GetValue(column.Content?.ToString())));
            }
        }
        else
        {
            foreach (object? item in source)
            {
                Children.Add(GenerateCell(item));
            }
        }

        _isCellsInitialized = true;
    }


    private Panel? FindParentPanel()
    {
        Panel? panel = null;

        // DataTableViewRow 应当出现在 ListView 的 ItemTemplate 中，此时，在向 ListView 的 ItemsPresenter
        // 添加元素时，会依据模板定义向 DataTableViewRow 的 Children 集合中添加元素，此时，控件的顺序应当如下：
        //       ListView
        //           |
        //           V
        //  HeaderContentPresenter
        //     ItemsPresenter
        //           |
        //           V
        //     DataTableViewRow
        //           |
        //           V
        //      ItemTemplate

        if (this.FindAscendant<ScrollViewer>()?.FindName("HeaderContentPresenter") is ContentPresenter headerPresenter)
        {
            panel = headerPresenter.FindDescendant<Panel>(e => e is Grid or DataTableView);
        }

        return panel;
    }


    private void InitializeParentPresenter()
    {
        if (HeaderTable is not null || _headerPanel is not null)
        {
            return;
        }

        _headerPanel ??= FindParentPanel();

        if (_headerPanel is DataTableView view)
        {
            view.AddRow(this);
        }
    }


    protected override Size MeasureOverride(Size availableSize)
    {
        InitializeParentPresenter();

        double maxHeight = 0;

        // 如果是空行，或者是隐藏行，高度应当是 0
        if (Children.Count == 0 || Visibility == Visibility.Collapsed)
        {
            return new Size(_headerPanel?.DesiredSize.Width ?? availableSize.Width, maxHeight);
        }

        // 在计算各个成员控件的尺寸时，应当考虑 ListView 的列设置情况：
        //   1. 如果 ItemsPresenter.Header 是 DataTableView，使用 DataTableViewColumn 的定义。
        //   2. 如果 ItemsPresenter.Header 是 Grid，使用 Grid.ColumnDefinitions 集合的列定义。

        // 如果没有包含当前行的容器控件，则遍历各个成员控件，获取最大高度。
        if (_headerPanel is null)
        {
            foreach (UIElement? control in Children)
            {
                control.Measure(availableSize);
                maxHeight = Math.Max(maxHeight, control.DesiredSize.Height);
            }

            return new Size(availableSize.Width, maxHeight);
        }

        // 如果 ListView.ItemsPresenter.Header 是 DataTableView，使用 DataTableView 的列定义，
        // 在定义时，DataTableViewColumn 作为子控件添加到 DataTableView.Children 集合中。
        if (HeaderTable is not null)
        {
            for (int i = 0; i < HeaderTable.Children.Count; i++)
            {
                // 只渲染列定义数量的子控件
                if (i >= Children.Count)
                {
                    break;
                }

                if (HeaderTable.Children[i] is not DataTableViewColumn column)
                {
                    continue;
                }

                UIElement? child = Children[i];
                child.Measure(new Size(column.DesiredSize.Width, availableSize.Height));
                maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
            }
        }
        // 如果 ListView.ItemsPresenter.Header 是 Grid，遍历 Grid.ColumnDefinitions 定义集合
        else if (_headerPanel is Grid grid)
        {
            for (int i = 0; i < grid.ColumnDefinitions.Count; i++)
            {
                // 只渲染列定义数量的子控件
                if (i >= Children.Count)
                {
                    break;
                }

                ColumnDefinition? columnDef = grid.ColumnDefinitions[i];
                UIElement? child = Children[i];

                if (columnDef.Width.GridUnitType == GridUnitType.Pixel)
                {
                    child.Measure(new Size(columnDef.Width.Value, availableSize.Height));
                }
                else
                {
                    child.Measure(availableSize);
                }

                maxHeight = Math.Max(maxHeight, child.DesiredSize.Height);
            }
        }

        return new Size(_headerPanel?.DesiredSize.Width ?? availableSize.Width, maxHeight);
    }


    protected override Size ArrangeOverride(Size finalSize)
    {
        if (_headerPanel is null)
        {
            return finalSize;
        }

        double[] sizeArray = [];

        if (HeaderTable != null)
        {
            sizeArray = HeaderTable.Children.OfType<DataTableViewColumn>()
                .Select(c => c.ActualWidth)
                .ToArray();
        }
        else if (_headerPanel is Grid grid)
        {
            sizeArray = grid.ColumnDefinitions.Select(c => c.ActualWidth).ToArray();
        }

        int index = 0;
        double x = 0;

        foreach (double size in sizeArray)
        {
            if (index >= Children.Count)
            {
                break;
            }

            Children[index].Arrange(new Rect(x, 0, size, finalSize.Height));
            x += size;
            index++;
        }

        return new Size(x, finalSize.Height);
    }
}